package cn.iocoder.yudao.module.system.service.record;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.iocoder.yudao.framework.common.exception.ServiceException;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.infra.service.config.ConfigService;
import cn.iocoder.yudao.module.system.controller.admin.application.vo.ApplicationSaveReqVO;
import cn.iocoder.yudao.module.system.controller.admin.record.vo.ApprovalRecordPageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.record.vo.ApprovalRecordSaveReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.application.ApplicationDO;
import cn.iocoder.yudao.module.system.dal.dataobject.nodeconfig.NodeConfigDO;
import cn.iocoder.yudao.module.system.dal.dataobject.record.ApprovalRecordDO;
import cn.iocoder.yudao.module.system.dal.mysql.application.ApplicationMapper;
import cn.iocoder.yudao.module.system.dal.mysql.record.ApprovalRecordMapper;
import cn.iocoder.yudao.module.system.enums.ApprovalConstants;
import cn.iocoder.yudao.module.system.enums.application.ApplicationEnums;
import cn.iocoder.yudao.module.system.service.nodeconfig.NodeConfigService;
import cn.iocoder.yudao.module.system.service.portal.PortalUserService;
import cn.iocoder.yudao.module.system.util.MsgUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.List;

/**
 * 审核操作记录 Service 实现类
 *
 * @author 芋道源码
 */
@Service
@Validated
public class ApprovalRecordServiceImpl implements ApprovalRecordService {

    private static final Logger log = LoggerFactory.getLogger(ApprovalRecordServiceImpl.class);

    @Resource
    private ApprovalRecordMapper recordMapper;
    @Resource
    private NodeConfigService nodeConfigService;
    @Resource
    private ApplicationMapper applicationMapper;
    @Resource
    private PortalUserService userService;
    @Resource
    private ConfigService configService;

    // ======================== 基础CRUD方法 ========================
    @Override
    public Integer createRecord(ApprovalRecordSaveReqVO createReqVO) {
        ApprovalRecordDO record = BeanUtils.toBean(createReqVO, ApprovalRecordDO.class);
        recordMapper.insert(record);
        log.info("创建审核记录：recordId={}, applicationId={}", record.getId(), record.getApplicationId());
        return record.getId();
    }

    @Override
    public void updateRecord(ApprovalRecordSaveReqVO updateReqVO) {
        ApprovalRecordDO updateObj = BeanUtils.toBean(updateReqVO, ApprovalRecordDO.class);
        recordMapper.updateById(updateObj);
        log.info("更新审核记录：recordId={}, applicationId={}", updateObj.getId(), updateObj.getApplicationId());
    }

    @Override
    public void deleteRecord(Integer id) {
        recordMapper.deleteById(id);
        log.info("删除审核记录：recordId={}", id);
    }

    @Override
    public void deleteRecordListByIds(List<Integer> ids) {
        recordMapper.deleteByIds(ids);
        log.info("批量删除审核记录：recordIds={}", ids);
    }

    @Override
    public ApprovalRecordDO getRecord(Integer id) {
        return recordMapper.selectById(id);
    }

    @Override
    public PageResult<ApprovalRecordDO> getRecordPage(ApprovalRecordPageReqVO pageReqVO) {
        return recordMapper.selectPage(pageReqVO);
    }

    // ======================== 核心业务方法 ========================
    @Override
    public void createAudit(ApplicationSaveReqVO createReqVO) throws Exception {
        // 1. 基础参数校验
        if (createReqVO == null || createReqVO.getId() == null) {
            throw new ServiceException(500, "申请信息或ID不能为空");
        }
        Integer applicationId = createReqVO.getId();
        String operator = getCurrentLoginUserId();
        log.info("初始化审核流程：applicationId={}, operator={}", applicationId, operator);

        // 2. 处理LEFT_1节点
        createLeft1NodeRecord(applicationId, operator);
        // 3. 处理RIGHT节点
        createRightNodeRecord(applicationId, operator, createReqVO.getCatalogId());
    }

    @Override
    @Transactional
    public Boolean auditApplication(ApprovalRecordSaveReqVO auditReqVO) throws Exception {
        // 1. 审核通过逻辑
        if (ApprovalConstants.AUDIT_RESULT_PASS.equals(auditReqVO.getAuditResult())) {
            updateRecordToPass(auditReqVO);
            createNextRecord(auditReqVO); // 创建下一节点记录
        }
        // 2. 审核不通过逻辑
        else if (ApprovalConstants.AUDIT_RESULT_REJECT.equals(auditReqVO.getAuditResult())) {
            updateRecordToReject(auditReqVO);
            // 删除其余未完成节点 + 更新应用状态为不通过
            recordMapper.deleteByApplicationIdAndCompleteStatus(auditReqVO.getApplicationId());
            applicationMapper.updateStatus(auditReqVO.getApplicationId(), ApprovalConstants.APPLICATION_STATUS_REJECT);
            log.info("审核不通过：applicationId={}, recordId={}", auditReqVO.getApplicationId(), auditReqVO.getId());
        }
        return Boolean.TRUE;
    }

    @Override
    public ApprovalRecordDO getAuditRecord(ApprovalRecordPageReqVO pageReqVO) {
        return recordMapper.getAuditRecord(pageReqVO);
    }

    // ======================== 节点流转相关方法 ========================
    /**
     * 创建下一节点审核记录（入口方法，按当前节点分发逻辑）
     */
    private void createNextRecord(ApprovalRecordSaveReqVO auditReqVO) throws Exception {
        String currentNodeCode = auditReqVO.getCurrentNodeCode();
        String operator = getCurrentLoginUserId();
        Integer applicationId = auditReqVO.getApplicationId();

        // 根据当前节点分发到对应流转逻辑
        switch (currentNodeCode) {
            case ApprovalConstants.NODE_LEFT_1:
                createNextFromLeft1(applicationId, operator);
                break;
            case ApprovalConstants.NODE_LEFT_2:
                createNextFromLeft2(applicationId, operator);
                break;
            case ApprovalConstants.NODE_LEFT_3:
                createNextFromLeft3OrRight(applicationId, operator, currentNodeCode);
                break;
            case ApprovalConstants.NODE_RIGHT:
                createNextFromLeft3OrRight(applicationId, operator, currentNodeCode);
                break;
            case ApprovalConstants.NODE_DEPT_SELECT:
                createNextFromDeptSelect(applicationId, operator, auditReqVO.getAuditor());
                break;
            case ApprovalConstants.NODE_DEPT_AUDIT:
                createNextFromDeptAudit(applicationId, operator);
                break;
            case ApprovalConstants.NODE_LEADER_AUDIT:
                createNextFromLeaderAudit(applicationId, operator);
                break;
            default:
                throw new ServiceException(500, "不支持的节点流转：" + currentNodeCode);
        }
    }

    /** LEFT_1节点 → LEFT_2节点 */
    private void createNextFromLeft1(Integer applicationId, String operator) throws Exception {
        NodeConfigDO left2Node = getNodeConfigByCode(ApprovalConstants.NODE_LEFT_2);
        AuditorInfo left2AuditorInfo = getFirstAuditorInfoFromJson(left2Node.getAuditor());

        createApprovalRecord(applicationId, operator, ApprovalConstants.NODE_LEFT_2,
                left2AuditorInfo.getDept(), left2AuditorInfo.getTelephone(), left2AuditorInfo.getMobile(),
                ApprovalConstants.OPERATION_TYPE_AUDIT);
    }

    /** LEFT_2节点 → LEFT_3节点 */
    private void createNextFromLeft2(Integer applicationId, String operator) throws Exception {
        NodeConfigDO left3Node = getNodeConfigByCode(ApprovalConstants.NODE_LEFT_3);
        AuditorInfo left3AuditorInfo = getFirstAuditorInfoFromJson(left3Node.getAuditor());

        createApprovalRecord(applicationId, operator, ApprovalConstants.NODE_LEFT_3,
                left3AuditorInfo.getDept(), left3AuditorInfo.getTelephone(), left3AuditorInfo.getMobile(),
                ApprovalConstants.OPERATION_TYPE_AUDIT);
    }

    /** LEFT_3/RIGHT节点 → DEPT_SELECT节点（合并重复逻辑） */
    private void createNextFromLeft3OrRight(Integer applicationId, String operator, String currentNodeCode) throws Exception {
        // 待检查的节点：当前是LEFT_3则查RIGHT，当前是RIGHT则查LEFT_3
        String checkNodeCode = ApprovalConstants.NODE_LEFT_3.equals(currentNodeCode)
                ? ApprovalConstants.NODE_RIGHT
                : ApprovalConstants.NODE_LEFT_3;

        ApprovalRecordDO checkRecord = recordMapper.getRecordByApplicationIdAndNodeCode(applicationId, checkNodeCode);
        // 若待检查节点已通过，创建DEPT_SELECT节点
        if (checkRecord != null && ApprovalConstants.AUDIT_RESULT_PASS.equals(checkRecord.getAuditResult())) {
            NodeConfigDO deptSelectNode = getNodeConfigByCode(ApprovalConstants.NODE_DEPT_SELECT);
            AuditorInfo deptSelectAuditorInfo = getFirstAuditorInfoFromJson(deptSelectNode.getAuditor());

            createApprovalRecord(applicationId, operator, ApprovalConstants.NODE_DEPT_SELECT,
                    deptSelectAuditorInfo.getDept(), deptSelectAuditorInfo.getTelephone(), deptSelectAuditorInfo.getMobile(),
                    ApprovalConstants.OPERATION_TYPE_ASSIGN);
        }
    }

    /** DEPT_SELECT节点 → DEPT_AUDIT节点（批量创建多审批人记录） */
    private void createNextFromDeptSelect(Integer applicationId, String operator, String auditorStr) throws Exception {
        if (StringUtils.isBlank(auditorStr)) {
            throw new ServiceException(500, "DEPT_SELECT节点未配置审批人");
        }

        String[] auditors = auditorStr.split(",");
        for (String auditor : auditors) {
            if (StringUtils.isNotBlank(auditor)) {
                NodeConfigDO deptAuditNode = getNodeConfigByCode(ApprovalConstants.NODE_DEPT_AUDIT);
                AuditorInfo deptAuditAuditorInfo = getAuditorInfoByDept(deptAuditNode.getAuditor(), auditor.trim());

                createApprovalRecord(applicationId, operator, ApprovalConstants.NODE_DEPT_AUDIT,
                        deptAuditAuditorInfo.getDept(), deptAuditAuditorInfo.getTelephone(), deptAuditAuditorInfo.getMobile(),
                        ApprovalConstants.OPERATION_TYPE_AUDIT);
            }
        }
    }

    /** DEPT_AUDIT节点 → LEADER_AUDIT节点（需所有DEPT_AUDIT完成） */
    private void createNextFromDeptAudit(Integer applicationId, String operator) throws Exception {
        List<ApprovalRecordDO> deptAuditRecords = recordMapper.getRecordListByApplicationIdAndNodeCode(
                applicationId, ApprovalConstants.NODE_DEPT_AUDIT);
        // 检查是否所有DEPT_AUDIT节点都已完成
        long finishedCount = deptAuditRecords.stream()
                .filter(record -> ApprovalConstants.COMPLETE_STATUS_FINISHED.equals(record.getCompleteStatus()))
                .count();

        if (deptAuditRecords.size() == finishedCount) {
            NodeConfigDO leaderAuditNode = getNodeConfigByCode(ApprovalConstants.NODE_LEADER_AUDIT);
            AuditorInfo leaderAuditorInfo = getFirstAuditorInfoFromJson(leaderAuditNode.getAuditor());

            createApprovalRecord(applicationId, operator, ApprovalConstants.NODE_LEADER_AUDIT,
                    leaderAuditorInfo.getDept(), leaderAuditorInfo.getTelephone(), leaderAuditorInfo.getMobile(),
                    ApprovalConstants.OPERATION_TYPE_AUDIT);
        }
    }

    /** LEADER_AUDIT节点 → NOTIFY节点（最终节点，更新应用状态为通过） */
    private void createNextFromLeaderAudit(Integer applicationId, String operator) throws Exception {
        NodeConfigDO notifyNode = getNodeConfigByCode(ApprovalConstants.NODE_NOTIFY);
        AuditorInfo notifyAuditorInfo = getFirstAuditorInfoFromJson(notifyNode.getAuditor());

        // 创建通知节点记录
        createApprovalRecord(applicationId, operator, ApprovalConstants.NODE_NOTIFY,
                notifyAuditorInfo.getDept(), notifyAuditorInfo.getTelephone(), notifyAuditorInfo.getMobile(),
                ApprovalConstants.OPERATION_TYPE_ASSIGN);
        // 更新应用状态为审核通过
        applicationMapper.updateStatus(applicationId, ApprovalConstants.APPLICATION_STATUS_PASS);
        log.info("审核流程完成（通过）：applicationId={}", applicationId);
    }

    // ======================== 初始化节点记录方法 ========================
    /** 初始化LEFT_1节点记录 */
    private void createLeft1NodeRecord(Integer applicationId, String operator) throws Exception {
        NodeConfigDO left1Node = getNodeConfigByCode(ApprovalConstants.NODE_LEFT_1);
        AuditorInfo left1AuditorInfo = getFirstAuditorInfoFromJson(left1Node.getAuditor());

        createApprovalRecord(applicationId, operator, ApprovalConstants.NODE_LEFT_1,
                left1AuditorInfo.getDept(), left1AuditorInfo.getTelephone(), left1AuditorInfo.getMobile(),
                ApprovalConstants.OPERATION_TYPE_AUDIT);
    }

    /** 初始化RIGHT节点记录（需根据数源单位匹配审批人） */
    private void createRightNodeRecord(Integer applicationId, String operator, String catalogId) throws Exception {
        // 获取数源单位ID
        String sourceDeptId = recordMapper.getSourceDeptId(catalogId);
        if (StringUtils.isBlank(sourceDeptId)) {
            throw new ServiceException(500, "未获取到数源单位ID");
        }

        // 获取RIGHT节点配置及匹配的审批人
        NodeConfigDO rightNode = getNodeConfigByCode(ApprovalConstants.NODE_RIGHT);
        AuditorInfo rightAuditorInfo = getAuditorInfoBySourceDeptId(rightNode.getAuditor(), sourceDeptId);
        if (StringUtils.isBlank(rightAuditorInfo.getDept())) {
            throw new ServiceException(500,
                    "RIGHT节点未找到与数源单位[" + sourceDeptId + "]匹配的审批人");
        }

        createApprovalRecord(applicationId, operator, ApprovalConstants.NODE_RIGHT,
                rightAuditorInfo.getDept(), rightAuditorInfo.getTelephone(), rightAuditorInfo.getMobile(),
                ApprovalConstants.OPERATION_TYPE_AUDIT);
    }

    // ======================== 通用工具方法 ========================
    /** 获取当前登录用户ID（抽取重复逻辑） */
    private String getCurrentLoginUserId() {
        return String.valueOf(SecurityFrameworkUtils.getPortalLoginUserId());
    }

    /** 根据节点编码获取节点配置（不存在则抛异常） */
    private NodeConfigDO getNodeConfigByCode(String nodeCode) {
        NodeConfigDO nodeConfig = nodeConfigService.getNodeByCode(nodeCode);
        if (nodeConfig == null) {
            throw new ServiceException(500, "未找到节点配置：" + nodeCode);
        }
        return nodeConfig;
    }

    /** 通用创建审批记录方法（添加座机和手机号字段） */
    private void createApprovalRecord(Integer applicationId, String operator, String nodeCode,
                                      String auditor, String telephone, String mobile, String operationType) {
        // 审批人非空校验
        if (StringUtils.isBlank(auditor)) {
            throw new ServiceException(500, nodeCode + "节点未配置有效的审批人");
        }

        // 1. 先创建审批记录（核心业务，优先保证成功）
        ApprovalRecordDO record = new ApprovalRecordDO();
        record.setApplicationId(applicationId);
        record.setCurrentNodeCode(nodeCode);
        record.setOperator(operator);
        record.setOperationType(operationType);
        record.setAuditor(auditor);
        record.setMobile(mobile);
        // 仅审核类型需要设置待审核结果
        if (ApprovalConstants.OPERATION_TYPE_AUDIT.equals(operationType)) {
            record.setAuditResult(ApprovalConstants.AUDIT_RESULT_PENDING);
        }
        record.setCompleteStatus(ApprovalConstants.COMPLETE_STATUS_PENDING);
        recordMapper.insert(record); // 先插入记录，确保核心业务成功

        // 2. 短信发送逻辑（非核心，失败不影响主流程）
        try {
            // 2.1 获取短信所需参数（放在try内，避免参数获取失败影响主流程）
            String userName = userService.getUserName(auditor);
            ApplicationDO applicationDO = applicationMapper.selectById(applicationId);
            if (applicationDO == null) {
                log.error("创建审批记录后，未找到申请信息：applicationId={}", applicationId);
                return; // 仅日志记录，不抛出异常
            }

            // 处理应用类型名称
            String dataServiceName = applicationDO.getApplicationTitle();
            for (ApplicationEnums.Type type : ApplicationEnums.Type.values()) {
                if (type.getCode().equals(applicationDO.getApplicationType())) {
                    dataServiceName = type.getName();
                    break;
                }
            }

            // 补充：获取申请标题（修复 'applicationTitle' 未定义问题）
            String applicationTitle = applicationDO.getApplicationTitle(); // 从applicationDO中获取

            // 组装申请时间（处理格式转换异常）
            String aapplicationTime = "";
            if (applicationDO.getCommitTime() != null) {
                try {
                    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH点mm分");
                    aapplicationTime = applicationDO.getCommitTime().format(formatter);
                } catch (DateTimeParseException e) {
                    log.error("时间格式转换失败，applicationId={}", applicationId, e);
                    aapplicationTime = "时间格式错误"; // 用默认值避免模板参数空值
                }
            }

            // 其他模板参数
            String platformName = "湖北省交通运输厅数据共享交换系统开放门户";
            String contact = configService.getConfigByKey("audit.userName").getValue();
            String contactInformation = configService.getConfigByKey("audit.phone").getValue();
            String applicant = userService.getUser(Long.valueOf(applicationDO.getCreateBy())).getNickName();

            // 构建模板参数JSON
            JSONObject templateParams = new JSONObject();
            templateParams.set("userName", userName);
            templateParams.set("dataServiceName", dataServiceName);
            templateParams.set("applicationTitle", applicationTitle); // 现在已定义，可正常使用
            templateParams.set("applicant", applicant);
            templateParams.set("aapplicationTime", aapplicationTime);
            templateParams.set("platformName", platformName);
            templateParams.set("contact", contact);
            templateParams.set("contactInformation", contactInformation);

            // 2.2 发送短信（手机号非空才发送）
            if (StringUtils.isNotBlank(telephone)) {
                // 增加短信发送重试机制（最多2次，避免临时网络问题）
                String smsResponse = null;
                int retryCount = 0;
                while (retryCount < 2) {
                    try {
                        smsResponse = MsgUtil.SendMsg(
                                MsgUtil.SIGN_NAME,
                                telephone,
                                MsgUtil.TEMPLATE_ID,
                                templateParams.toString()
                        );
                        break; // 成功则跳出重试
                    } catch (Exception e) {
                        retryCount++;
                        log.error("短信发送第{}次失败，接收人：{}，手机号：{}",
                                retryCount, auditor, telephone, e);
                        if (retryCount >= 2) {
                            throw e; // 重试后仍失败，记录最终异常
                        }
                        Thread.sleep(1000); // 间隔1秒重试
                    }
                }
                log.info("短信发送成功，接收人：{}，手机号：{}，节点：{}，响应：{}",
                        auditor, telephone, nodeCode, smsResponse);
            } else {
                log.warn("审批人[{}]手机号为空，跳过短信发送", auditor);
            }

        } catch (Exception e) {
            // 3. 短信发送失败的处理（仅记录日志，不影响审批记录创建）
            log.error("创建审批记录后，短信发送失败！applicationId={}, nodeCode={}, auditor={}, 请手动通知",
                    applicationId, nodeCode, auditor, e);

            // 可选：标记审批记录为“短信发送失败”，便于后续补偿（需在表中加字段，如sms_status）
            // record.setSmsStatus("FAIL");
            // recordMapper.updateById(record);
        }

        // 4. 最终日志（无论短信是否成功，都确认记录已创建）
        log.info("审批记录创建成功：applicationId={}, nodeCode={}, auditor={}, recordId={}",
                applicationId, nodeCode, auditor, record.getId());
    }

    /** 审批人信息封装类 */
    private static class AuditorInfo {
        private String auditor;
        private String telephone;
        private String mobile;

        public AuditorInfo(String auditor, String telephone, String mobile) {
            this.auditor = auditor;
            this.telephone = telephone;
            this.mobile = mobile;
        }

        public String getDept() {
            return auditor != null ? auditor : "";
        }

        public String getTelephone() {
            return telephone != null ? telephone : "";
        }

        public String getMobile() {
            return mobile != null ? mobile : "";
        }
    }

    /**
     * 从JSON中获取第一个审批人信息（包含部门、座机、手机）
     * 适配格式: {"auditor": "测试1", "telephone": "", "mobile": ""}
     */
    private AuditorInfo getFirstAuditorInfoFromJson(String auditorJson) {
        if (StringUtils.isBlank(auditorJson)) {
            throw new ServiceException(500, "审批人配置JSON为空");
        }
        if (!JSONUtil.isJson(auditorJson)) {
            throw new ServiceException(500, "审批人配置不是有效的JSON格式");
        }

        JSONObject jsonObject = JSONUtil.parseObj(auditorJson);

        // 直接从根节点获取审批人信息（对应单对象格式）
        String auditor = jsonObject.getStr("auditor", "");
        String telephone = jsonObject.getStr("telephone", "");
        String mobile = jsonObject.getStr("mobile", "");

        return new AuditorInfo(auditor, telephone, mobile);
    }

    /**
     * 根据数源单位ID匹配审批人信息（包含部门、座机、手机）
     * 适配格式: {"560":{"auditor":"","mobile":"","telephone":""}, "551": {...}}
     */
    private AuditorInfo getAuditorInfoBySourceDeptId(String auditorJson, String sourceDeptId) {
        if (StringUtils.isBlank(auditorJson)) {
            throw new ServiceException(500, "审批人配置JSON为空");
        }
        if (!JSONUtil.isJson(auditorJson)) {
            throw new ServiceException(500, "审批人配置不是有效的JSON格式");
        }
        if (StringUtils.isBlank(sourceDeptId)) {
            throw new ServiceException(500, "数源单位ID不能为空");
        }

        JSONObject jsonObject = JSONUtil.parseObj(auditorJson);
        // 获取指定数源单位ID对应的子对象
        JSONObject deptAuditorObj = jsonObject.getJSONObject(sourceDeptId);

        if (deptAuditorObj == null) {
            log.warn("未找到数源单位[{}]对应的审批人配置", sourceDeptId);
            return new AuditorInfo("", "", "");
        }

        // 从子对象中提取审批人信息
        String auditor = deptAuditorObj.getStr("auditor", "");
        String telephone = deptAuditorObj.getStr("telephone", "");
        String mobile = deptAuditorObj.getStr("mobile", "");

        return new AuditorInfo(auditor, telephone, mobile);
    }

    /** 根据部门名称匹配审批人信息 */
    private AuditorInfo getAuditorInfoByDept(String auditorJson, String deptName) {
        if (StringUtils.isBlank(auditorJson)) {
            throw new ServiceException(500, "审批人配置JSON为空");
        }
        if (!JSONUtil.isJson(auditorJson)) {
            throw new ServiceException(500, "审批人配置不是有效的JSON格式");
        }

        JSONObject jsonObject = JSONUtil.parseObj(auditorJson);

        // 尝试两种格式匹配：1. 根节点直接是审批人对象 2. 嵌套对象
        // 1. 检查是否为单对象格式
        if (jsonObject.containsKey("auditor")) {
            String auditor = jsonObject.getStr("auditor", "");
            if (deptName.equals(auditor)) {
                String telephone = jsonObject.getStr("telephone", "");
                String mobile = jsonObject.getStr("mobile", "");
                return new AuditorInfo(auditor, telephone, mobile);
            }
        }
        // 2. 检查是否为嵌套对象格式
        else {
            for (String key : jsonObject.keySet()) {
                JSONObject deptObj = jsonObject.getJSONObject(key);
                if (deptObj == null) continue;

                String auditor = deptObj.getStr("auditor", "");
                if (deptName.equals(auditor)) {
                    String telephone = deptObj.getStr("telephone", "");
                    String mobile = deptObj.getStr("mobile", "");
                    return new AuditorInfo(auditor, telephone, mobile);
                }
            }
        }

        log.warn("未找到部门[{}]对应的审批人配置", deptName);
        return new AuditorInfo("", "", "");
    }

    /** 更新记录为"审核通过"状态 */
    private void updateRecordToPass(ApprovalRecordSaveReqVO auditReqVO) {
        auditReqVO.setAuditResult(ApprovalConstants.AUDIT_RESULT_PASS);
        auditReqVO.setCompleteStatus(ApprovalConstants.COMPLETE_STATUS_FINISHED);
        auditReqVO.setCompleteTime(LocalDateTime.now());

        ApprovalRecordDO updateObj = BeanUtils.toBean(auditReqVO, ApprovalRecordDO.class);
        recordMapper.updateById(updateObj);
        log.info("审核通过：recordId={}, applicationId={}", updateObj.getId(), updateObj.getApplicationId());
    }

    /** 更新记录为"审核不通过"状态 */
    private void updateRecordToReject(ApprovalRecordSaveReqVO auditReqVO) {
        auditReqVO.setAuditResult(ApprovalConstants.AUDIT_RESULT_REJECT);
        auditReqVO.setCompleteStatus(ApprovalConstants.COMPLETE_STATUS_FINISHED);
        auditReqVO.setCompleteTime(LocalDateTime.now());

        ApprovalRecordDO updateObj = BeanUtils.toBean(auditReqVO, ApprovalRecordDO.class);
        recordMapper.updateById(updateObj);
    }
}